﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Maps.MapControl;
using MyFloridaHouse.libSvBingMapsMultiShape;
using MyFloridaHouse.libSvDTO;

namespace MyFloridaHouse.libSvOpenDistricts.MapShapes
{
    public static class MapShapeTools
    {
        public static MapMultiShapeBase BuildShape(int regionID, MapMultiShapeDTO mapMultiShapeDTO)
        {
            MapMultiShapeBase mapShape = null;

            if (mapMultiShapeDTO.shapeType == MapMultiShapeType.Point)
            {
                // ignore any points, just use the centerpoint.
                mapShape = null;
            }

            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.Polygon)
            {
                MapMultiPolygon newShape = new MapMultiPolygon();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.MultiPolygon)
            {
                MapMultiPolygon newShape = new MapMultiPolygon();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.LineString)
            {
                MapMultiPolyline newShape = new MapMultiPolyline();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.MultiLineString)
            {
                MapMultiPolyline newShape = new MapMultiPolyline();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else if (mapMultiShapeDTO.shapeType == MapMultiShapeType.GeometryCollection)
            {
                MapMultiGeometry newShape = new MapMultiGeometry();
                newShape.Vertices = GetMultiShapeLocationCollection(mapMultiShapeDTO);
                mapShape = newShape;
            }
            else
            {
                //Log.HandleInternalError("Unable to build shape for region [" + regionID.ToString() + "]");
                // ignore it
            }
            return mapShape;
        }

        private static IList<LocationCollection> GetMultiShapeLocationCollection(MapMultiShapeDTO multiShape)
        {
            List<LocationCollection> points = new List<LocationCollection>();
            foreach (var shape in multiShape.shapeList)
            {
                points.Add(ConvertPointDTOListToLocationCollection(shape.ExteriorRing));
                foreach (var interiorRing in shape.InteriorRings)
                {
                    points.Add(ConvertPointDTOListToLocationCollection(interiorRing));
                }
            }
            return points;
        }

        private static LocationCollection ConvertPointDTOListToLocationCollection(List<PointDTO> verticies)
        {
            LocationCollection locs = new LocationCollection();
            foreach (var vert in verticies)
            {
                Location mapLoc = new Location(vert.latitude, vert.longitude);
                locs.Add(mapLoc);
            }
            return locs;
        }


        public static MyFloridaHouse.libSvDTO.BoundingBoxDTO ConvertServiceBoundingBoxDTOtoLibSvDTO(MyFloridaHouse.ServiceConn.DistrBldrSvcRef.BoundingBoxDTO serverDTO)
        {
            //TODO:  Oh, this is ugly.  Need code to run bingMapMultiShapeDTO point reduction on both server and client.  
            //TODO: Temporary till we remove the DTO references from reflected through the server to shared DTO lib 
            // Have to get this out tomorrow, and am having trouble resolving references
            MyFloridaHouse.libSvDTO.BoundingBoxDTO newDTO = new libSvDTO.BoundingBoxDTO();
            newDTO.northWest = new PointDTO(serverDTO.northWest.latitude,serverDTO.northWest.longitude);
            newDTO.southEast = new PointDTO(serverDTO.southEast.latitude,serverDTO.southEast.longitude);
            return newDTO;
        }

        public static MyFloridaHouse.libSvDTO.MapMultiShapeDTO ConvertServiceDTOtoLibSvDTO(MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeDTO serverDTO)
        {
            //TODO:  Oh, this is ugly.  Need code to run bingMapMultiShapeDTO point reduction on both server and client.  
            //TODO: Temporary till we remove the DTO references from reflected through the server to shared DTO lib 
            // Have to get this out tomorrow, and am having trouble resolving references
            MyFloridaHouse.libSvDTO.MapMultiShapeDTO newDTO = new libSvDTO.MapMultiShapeDTO();
            newDTO.shapeList = new List<MyFloridaHouse.libSvDTO.MapMultiShapeEntryDTO>();
            foreach (var entry in serverDTO.shapeList)
            {
                MyFloridaHouse.libSvDTO.MapMultiShapeEntryDTO newEntry = new libSvDTO.MapMultiShapeEntryDTO();
                newEntry.shapeType = ConvertServiceMapMultiShapeTypeToLibSvDTO(entry.shapeType);
                newEntry.ExteriorRing = MapShapeTools.ConvertServiceMapMultiShapeRingToLibSvDTO(entry.ExteriorRing);
                newEntry.InteriorRings = new List<List<libSvDTO.PointDTO>>();
                foreach (var intring in entry.InteriorRings)
                {
                    newEntry.InteriorRings.Add(MapShapeTools.ConvertServiceMapMultiShapeRingToLibSvDTO(intring));
                }
                newDTO.shapeList.Add(newEntry);
            }
            newDTO.shapeType = ConvertServiceMapMultiShapeTypeToLibSvDTO(serverDTO.shapeType);
            return newDTO;
        }

        private static List<libSvDTO.PointDTO> ConvertServiceMapMultiShapeRingToLibSvDTO(ObservableCollection<MyFloridaHouse.ServiceConn.DistrBldrSvcRef.PointDTO> serverPointList)
        {
            //TODO:  Oh, this is ugly too!  
            List<libSvDTO.PointDTO> convertedPointList = new List<libSvDTO.PointDTO>();
            foreach (var pnt in serverPointList)
            {
                convertedPointList.Add(new libSvDTO.PointDTO(pnt.latitude, pnt.longitude));
            }
            return convertedPointList;
        }

        private static MyFloridaHouse.libSvDTO.MapMultiShapeType ConvertServiceMapMultiShapeTypeToLibSvDTO(MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeType serverType)
        {
            //TODO:  Oh, this is ugly too!
            MyFloridaHouse.libSvDTO.MapMultiShapeType newShapeType = new libSvDTO.MapMultiShapeType();
            if (serverType == MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeType.GeometryCollection) newShapeType = libSvDTO.MapMultiShapeType.GeometryCollection;
            else if (serverType == MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeType.LineString) newShapeType = libSvDTO.MapMultiShapeType.LineString;
            else if (serverType == MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeType.MultiLineString) newShapeType = libSvDTO.MapMultiShapeType.MultiLineString;
            else if (serverType == MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeType.MultiPolygon) newShapeType = libSvDTO.MapMultiShapeType.MultiPolygon;
            else if (serverType == MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeType.Point) newShapeType = libSvDTO.MapMultiShapeType.Point;
            else if (serverType == MyFloridaHouse.ServiceConn.DistrBldrSvcRef.MapMultiShapeType.Polygon) newShapeType = libSvDTO.MapMultiShapeType.Polygon;
            else newShapeType = libSvDTO.MapMultiShapeType.Empty;
            return newShapeType;
        }

        internal static List<MyFloridaHouse.libSvDTO.RegionDTO> ConvertServiceRegionDTOListtoLibSvDTO(List<ServiceConn.DistrBldrSvcRef.RegionDTO> serverRegionList)
        {
            //TODO: More ugliness until I can remove the DTO references through the service
            List<RegionDTO> newRegionDTOList = new List<RegionDTO>();

            foreach (var rgn in serverRegionList)
            {
                RegionDTO region = new RegionDTO();

                region.boundingBox = new BoundingBoxDTO(rgn.boundingBox.northWest.latitude, rgn.boundingBox.northWest.longitude, rgn.boundingBox.southEast.latitude, rgn.boundingBox.southEast.longitude);
                region.centerLatY = rgn.centerLatY;
                region.centerLngX = rgn.centerLngX;
                region.mapMultiShapeDTO = ConvertServiceDTOtoLibSvDTO(rgn.mapMultiShapeDTO);
                region.regionID = rgn.regionID;
                region.name = rgn.name;
                newRegionDTOList.Add(region);
            }
            return newRegionDTOList;
        }

    }
}
